package com.aplink.generic.xmlparser;

import android.content.Context;
import android.content.res.Resources;

import com.aplink.generic.constant.ConfigParameter;
import com.aplink.generic.pojo.JoinCol;
import com.aplink.generic.pojo.ObjPropCol;
import com.aplink.generic.pojo.ObjPropInfo;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import java.io.IOException;
import java.util.HashMap;

import javax.xml.parsers.ParserConfigurationException;

public class ObjPropInfoParser {

    private static String getTextNodeValue( Node node ) {
        Node child;
        if ( node != null ) {
            if ( node.hasChildNodes() ) {
                child = node.getFirstChild();
                while ( child != null ) {
                    if ( child.getNodeType() == Node.TEXT_NODE ) {
                        return child.getNodeValue();
                    }
                    child = child.getNextSibling();
                }
            }
        }
        return "";
    }

    private static ObjPropCol parse( Document doc, String tagname,
                                     String objectId ) {
        ObjPropCol objPropCol = new ObjPropCol();
        Element propElement = doc.getDocumentElement();
        String webserviceFunction = propElement
                .getAttribute( ConfigParameter.DISP_PROP_WEB_SERVICE_FUNCTION );
        if ( webserviceFunction != null ) {
            objPropCol.setWebserviceFunction( webserviceFunction );
        }

        final NodeList nList = doc.getElementsByTagName( tagname );

        for ( int temp = 0 ; temp < nList.getLength() ; temp++ ) {
            final Node nNode = nList.item( temp );
            String p_om_id = null;
            final ObjPropInfo objPropInfo = new ObjPropInfo();
            boolean isSortedAsc = false;
            boolean isSortedDesc = false;
            if ( nNode.getParentNode().getAttributes() != null ) {
                p_om_id = XMLPaserUtil.getAttrValue( nNode.getParentNode(),
                        ConfigParameter.OBJ_PROP_P_OM_ID );
                objPropInfo.setPrimaryObjectMapping( p_om_id );
            }

            if ( nNode.getNodeType() == Node.ELEMENT_NODE ) {
                String content = "";
                final Element element = (Element) nNode;

                if ( element.hasAttributes() ) {
                    String sortASC = XMLPaserUtil.getAttrValue( nNode,
                            ConfigParameter.OBJ_PROP_IS_SORTED_ASC );
                    String sortDESC = XMLPaserUtil.getAttrValue( nNode,
                            ConfigParameter.OBJ_PROP_IS_SORTED_DESC );

                    if ( sortASC != null && sortASC.equalsIgnoreCase( "Y" ) ) {
                        isSortedAsc = true;
                    } else if ( sortDESC != null
                            && sortDESC.equalsIgnoreCase( "Y" ) ) {
                        isSortedDesc = true;
                    }
                }
                // get ID of this property
                NodeList nodes = element
                        .getElementsByTagName( ConfigParameter.OBJ_CLASS_ID );
                if ( nodes.getLength() != 0 ) {
                    content = getTextNodeValue( nodes.item( 0 ) );
                    objPropInfo.setObjectMapping( content ); // done
                }

                // get ID of this property
                nodes = element
                        .getElementsByTagName( ConfigParameter.OBJ_PROP_ID );
                if ( nodes.getLength() != 0 ) {
                    content = getTextNodeValue( nodes.item( 0 ) );
                    objPropInfo.setObjectProperty( content );
                }

                if ( isSortedAsc ) {
                    objPropCol.addSortAscending( objPropInfo.getObjectMapping(),
                            objPropInfo.getObjectProperty() );
                } else if ( isSortedDesc ) {
                    objPropCol.addSortDecending( objPropInfo.getObjectMapping(),
                            objPropInfo.getObjectProperty() );
                }

                // check isKey,
                final Node nNodeID = nodes.item( 0 );
                final Element elementchild = (Element) nNodeID;
                final String iskey = elementchild
                        .getAttribute( ConfigParameter.OBJ_PROP_ISKEY );
                if ( iskey.equalsIgnoreCase( "Y" ) ) {
                    objPropInfo.setKey( true ); // done
                }

                // or (isFKey, fkeyID)
                final String isfkey = elementchild
                        .getAttribute( ConfigParameter.OBJ_PROP_ISFKEY );
                if ( isfkey.equalsIgnoreCase( "Y" ) ) {
                    objPropInfo.setFKey( true ); // done
                }

                final String f_table_id = elementchild
                        .getAttribute( ConfigParameter.OBJ_PROP_F_OM_ID );
                if ( ! f_table_id.isEmpty() ) {
                    objPropInfo.setForeignObjectMapping( f_table_id ); // done
                }
                final String foriegnKeyId = elementchild
                        .getAttribute( ConfigParameter.OBJ_PROP_FKEYID );
                if ( ! foriegnKeyId.isEmpty() ) {
                    objPropInfo.setForiegnKey( foriegnKeyId );
                }

                // we check isAccountId or not
                final String isAccountId = elementchild
                        .getAttribute( ConfigParameter.OBJ_PROP_ISACCOUNTID );
                if ( isAccountId.equalsIgnoreCase( "Y" ) ) {
                    objPropInfo.setAccountId( true );
                }

                // we check isPassId or not
                final String isAccountPass = elementchild
                        .getAttribute( ConfigParameter.OBJ_PROP_ISACCOUNTPASS );
                if ( isAccountPass.equalsIgnoreCase( "Y" ) ) {
                    objPropInfo.setAccountPass( true );
                }

                // get datatype of this property
                nodes = element
                        .getElementsByTagName( ConfigParameter.OBJ_PROP_DATATYPE );
                if ( nodes.getLength() != 0 ) {
                    content = getTextNodeValue( nodes.item( 0 ) );
                    objPropInfo.setDataType( content ); // done
                }

                // get name of this property
                nodes = element
                        .getElementsByTagName( ConfigParameter.OBJ_PROP_NAME );
                if ( nodes.getLength() != 0 ) {
                    content = getTextNodeValue( nodes.item( 0 ) );
                    objPropInfo.setPropName( content ); // done
                }

                if ( objPropInfo.isKey() ) {
                    objPropCol.setKeyProp( objPropInfo );
                }

                if ( p_om_id != null ) {
                    HashMap<String, ObjPropCol> cobjs = objPropCol
                            .getChildObjProps();
                    ObjPropCol childObjs = (ObjPropCol) cobjs.get( objPropInfo
                            .getObjectMapping() );
                    if ( childObjs == null ) {
                        childObjs = new ObjPropCol();
                        cobjs.put( objPropInfo.getObjectMapping(), childObjs );
                    }
                    childObjs.insert( objPropInfo.getObjectProperty(),
                            objPropInfo );
                    objPropCol.setChildObjProps( cobjs );
                }
                if ( objPropInfo.isFKey() ) {
                    JoinCol joins = objPropCol.getJoins();
                    String col = null;
                    if ( objPropInfo.getFKeyID() == null ) {
                        col = objPropInfo.getObjectProperty();
                    } else {
                        col = objPropInfo.getFKeyID();
                    }
                    if ( joins == null ) {
                        joins = new JoinCol();
                    }
                    if ( p_om_id.equalsIgnoreCase( objectId ) ) {
                        joins.AddJoin(
                                objectId,
                                objPropInfo.getObjectMapping(),
                                objectId + "." + col + "="
                                        + objPropInfo.getObjectMapping() + "."
                                        + objPropInfo.getObjectProperty() );
                    } else {
                        joins.AddJoin(
                                objPropInfo.getPrimaryObjectMapping(),
                                objPropInfo.getObjectMapping(),
                                objPropInfo.getPrimaryObjectMapping() + "."
                                        + col + "="
                                        + objPropInfo.getObjectMapping() + "."
                                        + objPropInfo.getObjectProperty() );
                    }
                    objPropCol.setJoins( joins );
                }

                if ( objPropCol.containsKey( objPropInfo.getObjectProperty() ) == false ) {
                    objPropCol.insert( objPropInfo.getObjectProperty(),
                            objPropInfo );
                } else {
                    if ( objPropInfo.isFKey() ) {
                        objPropCol.set( objPropInfo.getObjectProperty(),
                                objPropInfo );
                    }
                }
            }
        }
        return objPropCol;
    }

    public static ObjPropCol parseIntoObjProp( Context paramContext,
                                               int xmlFileId, String tagname, String objectId ) {
        try {
            final Document document = XMLPaserUtil.openDocumentFrom(
                    paramContext, xmlFileId );
            return parse( document, tagname, objectId );
        } catch ( final ParserConfigurationException e ) {
            e.printStackTrace();
        } catch ( final SAXException e ) {
            e.printStackTrace();
        } catch ( final IOException e ) {
            e.printStackTrace();
        } catch ( final Resources.NotFoundException e ) {
            e.printStackTrace();
        }
        return new ObjPropCol();
    }
}
